developmentsedit button

문서를 먼저 작성하면 달라지는 것들

14 min read|24. 10. 6.

profit-of-documentation-first

'한 페이지가 될 수 있게'

DAY6라는 좋아하는 밴드의 곡이다. 잠깐 드럼을 연주했을 때 이 곡의 드럼이 참 어렵다는 이야기를 들었다. 문서 이야기를 하려다보니 생각났다.

'문서 작성'이라고 하면 어떤 템플릿에 맞춰 작성해야 할 것 같고 프로세스가 추가된 것 같다. 나는 한 스프린트가 2주, 총 10일이라면 하루 정도는 꼬박 문서를 쓴다. 이 문서엔 다음과 같은 내용들이 주로 담긴다.

  • 문제가 무엇인가
  • 이 문제를 해결하기 위해 가장 값싼 방법인가
  • 요구사항이 무엇인가
  • 숨어있는 요구사항은 무엇인가
  • 기능을 구현하기 위해 필요한 모듈들은 무엇인가?
  • 어떻게 코드를 작성할 것인가? (Pseudo code)
  • 배포, 모니터링, 롤백 플랜
  • 스프린트 회고
    • 놓친 요구사항
    • 공수가 제대로 파악되지 않았던 부분
    • 병목이 됐던 부분
  • 공유할 내용 정리
    • 만든 공통 모듈 공유
    • 새롭게 시도한 아키텍처, 코드 조각 공유

작성하는 이 문서는 개발 계획서, 명세서, 테크스펙(Tech spec), 요구사항 문서 등 많은 이름으로 불린다. 이 과정을 요구사항 분석, 문서 작성, 설계 등으로 부를 수 있는데 무엇을 해야하는지 구체화하는 과정이라고 할 수 있다.

더 나은 코드를 작성하기 위해

누구나 '좋은' 코드를 작성하고 싶다.

모듈의 인터페이스만 보고도 이 모듈이 어떤 역할을 하는지 파악할 수 있다면 이해하기 좋은 코드라고 할 수 있다. 모듈 내부 구현을 보지 않아도 되기 때문에 예측 가능한 코드가 된다. 이해하기 좋고 예측 가능한 직관적인 코드가 모이면 '표현력'이 높은 코드가 만들어진다.

이런 예측 가능한 인터페이스는 모듈이 하나의 역할만 수행할 때 만들어진다. 그리고 한 가지 역할을 하는 모듈들이 서로 협력할 때 표현력이 높은 코드가 만들어진다. 코드를 읽고 어떤 요구사항을 수행하고 있는지 알 수 있게 된다.

우리는 요구사항을 구현하기 전에 구현 대상을 '해체'하고 어떻게 구성할지 인터페이스를 고민해야 한다.

How

그렇다면 표현력이 높은 코드는 어떻게 작성할 수 있을까? 구현하면서 인터페이스를 좋게 만들면 되지 않을까?

대부분 구현을 우선한다. 이러는 데에는 나름의 이유가 있다. 일단 코드를 작성하는 것이 재밌다. 결과물이 빠르게 만들어지기 때문이다. 또 다른 이유는 팀이 빠르게 움직이길 바라는 마음에 급해지기 때문이다.

하지만 인터페이스를 정의하지 않고 요구사항을 구현하게 되면 '닫힌 사고'를 하게 된다. 인터페이스에 대한 고민이 비어있으니 구현이 인터페이스에 드러나게 된다. 구현이 드러난 인터페이스는 이해하기 어렵다. 무엇을 하는지 설명하지 않고 어떻게 동작하는지 설명하기 때문이다. 표현력이 낮은 코드는 이해하기 어렵고 수정하기 어렵다.

열린 사고 vs 닫힌 사고

무엇을 만들지 생각하는 뇌의 모드와 어떻게 구현할지 생각하는 뇌의 모드가 다르다.

구현을 위한 뇌의 모드는 '닫힌 사고' 모드이다. 논리적으로 옳아야 하며 복잡한 조건문을 신경쓴다. 컴파일 에러없이 동작 가능한 코드를 작성하는데 집중한다. 현재 스택에 어떤 변수들이 올라와 있는지, 컨텍스트에서 어떤 함수가 실행됐는지 파악하고 있다.

반면에 인터페이스를 상상하는 뇌의 모드는 '열린 사고' 모드이다. 이 기능을 구현하기 위해 어떤 모듈이 필요할지 생각한다. 모듈을 어떤 인터페이스로 표현했을 때 직관적일지 생각한다. 사람의 입장에서 생각하며 여러 모듈을 살펴보면서 비교해본다.

뇌의 모드에 따라 잘할 수 있는게 다르다. 모드가 다르기 때문에 구현하면서 좋은 인터페이스를 떠올리기 어렵다.

뇌의 모드에 따라 잘할 수 있는 것에 집중하고 컨텍스트 스위칭을 줄이면 어떨까? 먼저 열린 사고를 통해 인터페이스를 고민한다. 이런 인터페이스라면 직관적이지 않을까. 이런 기능을 담당하고 있는 모듈이 있다고 생각하면 어떨까. 나라면 어떻게 사용하려고 할까. 등 먼저 고민하여 인터페이스를 정리하고 구현에 들어가는 것이다.

구현해야 하는 요구사항을 해체하여 여러 기능 단위로 인터페이스를 정리하고 나면 여러 부수효과들이 나타난다.

부수효과 1. 효율

코드를 작성하지 않고 문제를 해결할 수 있다면 유지보수할 코드도 만들지 않게 된다. 또는 좀 더 쉽게 해결할 수 있는 UX를 제안하여 더 적은 코드로 문제를 해결할 수 있다.

필요한 모듈을 먼저 정의하고 나면 만들어진 모듈이 있는지 찾아볼 수 있다. 이미 개발된 모듈이 있다면 사용하거나 참고할 수 있다.

구현은 컴퓨터가 더 빠르다. 인터페이스를 잘 정의해두면 Copilot, Chatgpt, Claude 등의 Assistant를 활용해 구현을 빠르게 채워넣을 수 있다.

부수효과 2. 병렬

구현해야 하는 요구사항을 여러 모듈로 해체하는 작업이 끝났다면 각 작업간의 의존성을 파악할 수 있다. 서로 의존성이 없는 작업들은 병렬로 진행할 수 있다. 동료와 협업이 필요하거나 의사결정이 필요하여 작업에 병목이 발생할 경우, 의존성이 없는 작업으로 전환하여 작업을 계속 진행할 수 있다.

요구사항을 해체하지 않았다면 이번 스프린트 작업은 직렬로 진행해야 했고 병목이 생기면 일정에 영향을 줄 것이다.

부수효과 3. 생산성

해체한 모듈들은 요구사항과 직접적인 의존성이 없도록 설계된다. 구현하고자 하는 요구사항에서만 사용될 수 있는 모듈이 아니라 범용적으로(General purpose) 사용할 수 있는 모듈인 것이다. 이렇게 설계된 모듈은 추후 다른 요구사항 때도 사용할 수 있다.

이런 모듈들이 스프린트 때마다 쌓이면 팀의 기술 자산이 된다. 기술 자산이 쌓여 팀의 생산성이 되고 코드의 퀄리티가 상향 평준화 될 수 있다.

더 나아가 한 가지 역할에 집중하여 작성된 코드는 리뷰하기도 편하다. 자잘한 구현이 아닌 인터페이스에 초점을 맞춰 리뷰할 수 있고 서로의 관점을 공유할 수 있다.

부수효과 4. 예측 가능성

요구사항을 여러 작은 모듈로 잘 해체했다면 작업에 필요한 공수를 파악하기 수월해진다. 계산된 공수를 기반으로 구체적인 일정을 계획할 수 있으며 이렇게 공유된 일정은 팀이 목표를 달성하는데 도움이 된다.

마무리

문서 작성에 시간을 투자하는 이유와 이로 인한 부수효과를 정리했다. 구현이 눈에 보이더라도 숨겨진 요구사항이 있진 않는지, 더 나은 방법이 있진 않을지, VSCode를 잠시 닫고 문서 에디터를 열어 차분히 요구사항을 분석해 나가는 것이 중요하다.

정리

  1. 우리의 목적은 코드 작성이 아니다. 오히려 코드는 시간이 지나면 부채가 된다. 덜 개발하여 문제를 해결할 수도 있다.
  2. 시간은 가장 비싼 자원이다. 병렬로 개발하여 병목으로 인한 지연을 최소화 할 수 있다.
  3. 기술 자산은 복리다. 기술 자산을 축적하여 생산성이 우상향하는 팀을 만든다.
  4. 문제 해결에 걸리는 시간을 예측할 수 있다. 달성할 수 있는 목표도 구체적으로 산정할 수 있게 된다.

좀 더 잘해보기

  • 인터페이스 살펴보기
    • 고민만 하지 말고 많이 사용하는 오픈소스의 인터페이스를 공부하는 것도 많은 도움이 된다.
  • 테스트 코드 작성해보기
    • 좋은 코드는 무엇인가? 글에선 테스트 가능한 코드라는 결론을 지었는데, 테스트가 쉽도록 모듈을 개선하다보면 이해하기 좋은 코드가 만들어진다.
  • 함께 리뷰하며 관점 공유하기
    • 본격적으로 구현에 들어가기 전 작성한 문서를 동료들과 함께 리뷰해보면 좋다. 코드에 비해 문서는 수정하기 쉽기 때문에 피드백을 주고 받기 쉽다. 서로의 관점을 배울 수 있는 좋은 기회라고 생각한다.
  • 회고하며 모듈 설계를 더 잘해보기
    • 잘못 산정된 공수는 없는지 빠뜨린 요구사항은 없는지 등 회고하면 다음번엔 더 나은 설계를 할 수 있다.